package view;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JMenuBar;
import javax.swing.JButton;
import javax.swing.JTabbedPane;
import javax.swing.JPanel;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.ListSelectionModel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableColumnModelListener;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.JLabel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SpinnerListModel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

import exceptions.ExecaoHalt;
import exceptions.ExecaoInstrucaoInexistente;
import exceptions.ExecaoMnemonicoInexistente;
import exceptions.ExecaoMontador;
import exceptions.ExecaoNumeroForaDosLimites;
import exceptions.ExecaoRegistradorInexistente;
import exceptions.ExecaoRotuloNaoDefinido;
import exceptions.ExecaoRotuloSemInstrucao;

import basics.ConversaoDeBases;
import basics.OperacoesEmArquivo;

import model.LinhaDeExecucao;
import model.Simulador;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.filechooser.FileFilter;
import javax.xml.ws.handler.MessageContext.Scope;

import java.awt.Color;
import java.io.File;
import java.io.IOException;

public class Janela {
	
	private static long memoryStartValue = 0;
	private static long memoryEndValue = memoryStartValue + 399;

	private ArrayList<LinhaDeExecucao> listaDeExecucao;
	private JFrame frmMipsSimulator;
	private JTable tableMemory;
	private JTable tableExecute;
	private JTable tableRegister;
	private JTextArea textAreaConsole;
	
	
	private TextLineNumber tln;
	
	
	private DefaultTableModel tableModelExecute;
	
	private JButton btnNew = new JButton("New");
	private JButton btnOpen = new JButton("Open");
	private JButton btnSave = new JButton("Save");
	private JButton btnSaveAs = new JButton("Save as");
	private JButton btnAssemble = new JButton("Assemble");
	private JButton btnExecute = new JButton("Execute");
	private JButton btnStep = new JButton("Step");
	private JRadioButton rdbtnHexadecimalMemory;
	private JRadioButton rdbtnDecimalMemory;
	private JRadioButton rdbtnBinaryMemory;
	private JRadioButton rdbtnHexadecimalExecute;
	private JRadioButton rdbtnDecimalExecute;
	private JRadioButton rdbtnBinaryExecute;

	
	private JRadioButton rdbtnHexadecimalRegisters;
	private JRadioButton rdbtnDecimalRegisters;
	private JRadioButton rdbtnBinaryRegisters;
	
	private JEditorPane editorPaneCode;
	
	private JSpinner spinnerStart;
	
	private JTabbedPane tabbedPane;
	
	private JFileChooser jFChosen;

	//Simulador mips
	private Simulador mips;
	
	//caminho para salvar e abrir arquivos
	private String caminho = "";
	
	//valor máximo do endereço de memória
	private long tamanhoMemoria;
	
	//Array de registradores
	private String[] registradoresArray;
	//Array da memória
	private String[] memoriaArray;
		
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Janela window = new Janela();
					window.frmMipsSimulator.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	private void novoPrograma(){
		
		editorPaneCode.setEnabled(true);
		editorPaneCode.setText("");
		tabbedPane.setSelectedIndex(0);
		editorPaneCode.requestFocus();
		
		editorPaneCode.setBackground(new Color(255, 255, 255));
		btnSave.setEnabled(true);
		btnSaveAs.setEnabled(true);
		btnAssemble.setEnabled(true);
		btnExecute.setEnabled(false);
		btnStep.setEnabled(false);
	}
	
	private void salvar(){
				
		if (caminho.equals(""))
			salvarComo();
		else
			salvaArquivo(this.caminho);
	}
	
	private void abrir(){
		int retorno;
		
		if (!this.caminho.equals("")){
			gravarMudancas();
		}
		
		jFChosen.setDialogTitle("Abrir arquivo");		
		retorno = jFChosen.showOpenDialog(null);
		
		editorPaneCode.setText("");
		
		if (retorno == JFileChooser.APPROVE_OPTION){			
			abreArquivo(jFChosen.getSelectedFile().getAbsolutePath());
			
			editorPaneCode.setEnabled(true);
			editorPaneCode.setBackground(new Color(255, 255, 255));
			btnSave.setEnabled(true);
			btnSaveAs.setEnabled(true);
			btnAssemble.setEnabled(true);
			
			this.caminho = jFChosen.getSelectedFile().getAbsolutePath();
			
			tabbedPane.setSelectedIndex(0);
			editorPaneCode.requestFocus();
			btnExecute.setEnabled(false);
			btnStep.setEnabled(false);
		}
	}
	
	private void salvarComo(){
		int retorno;
		
		jFChosen.setDialogTitle("Salvar arquivo");		
		retorno = jFChosen.showSaveDialog(null);
		
		if (retorno == JFileChooser.APPROVE_OPTION){
			this.caminho = jFChosen.getSelectedFile().getAbsolutePath();
			salvaArquivo(this.caminho);
		}
	}
	
	private void abreArquivo(String caminho){
		
		ArrayList<String> assemblyCode;
		
		try {
			assemblyCode = OperacoesEmArquivo.leitura(caminho);
			
			for (int i = 0; i < assemblyCode.size(); i++) {
				editorPaneCode.setText(editorPaneCode.getText() + "\n" + assemblyCode.get(i));
			}
			
		} catch (IOException e) {
			
			// TODO Auto-generated catch block
			JOptionPane.showMessageDialog(frmMipsSimulator, "Error load file!", "Error", JOptionPane.YES_OPTION);
			abrir();			
		}
				
	}
	
	private void salvaArquivo(String caminho){
		
		ArrayList<String> assemblyCode = new ArrayList<String>();
		
		String[] s = editorPaneCode.getText().split("\n");
		
		for (int i = 0; i < s.length; i++) {
			
			assemblyCode.add(s[i]);
		}		
				
		try {
			OperacoesEmArquivo.escrita(caminho, assemblyCode);
			
			JOptionPane.showMessageDialog(frmMipsSimulator, "Files saved with sucess!", "Saved", JOptionPane.INFORMATION_MESSAGE);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			JOptionPane.showMessageDialog(frmMipsSimulator, "Error saving file!", "Error", JOptionPane.YES_OPTION);
			salvarComo();
		}		
	}
	
	private void assemble(){
		
		mips.inicializaSimulador();		
		
		ArrayList<String> assemblyCode = new ArrayList<String>();
		listaDeExecucao = new ArrayList<LinhaDeExecucao>();
		
		String[] s = editorPaneCode.getText().split("\n");
		
		for (int i = 0; i < s.length; i++) {
			
			assemblyCode.add(s[i]);
		}

		try {
			listaDeExecucao = mips.executaMontagem(assemblyCode);
			
			tableModelExecute.getDataVector().removeAllElements();
			tableModelExecute.setRowCount(0);
			
			for (int i = 0; i < listaDeExecucao.size(); i++) {
				tableModelExecute.addRow(new String[]{"", "", "", ""});
			}
			
			recarregaMemoria();
			recarregaRegistradores();
			
			btnExecute.setEnabled(true);
			btnStep.setEnabled(true);
			
			tableExecute.getColumnModel().getColumn(3).setCellRenderer(new RenderCell(mips.pc() < 0 ? 0 : mips.pc() / 4));
			tabbedPane.setSelectedIndex(1);
			tableExecute.repaint();


		} catch (ExecaoMnemonicoInexistente e) {
			// TODO Auto-generated catch block
			textAreaConsole.append("linha " + e.getLinha() + ": comando inexistente!\n");
		}
		 catch (ExecaoRegistradorInexistente e) {
				// TODO Auto-generated catch block
				textAreaConsole.append("linha " + e.getLinha() + ": registrador inexistente!\n");
			}
		 catch (ExecaoNumeroForaDosLimites e) {
				// TODO Auto-generated catch block
				textAreaConsole.append("linha " + e.getLinha() + ": número fora dos limites!\n");
			}
		 catch (ExecaoRotuloNaoDefinido e) {
				// TODO Auto-generated catch block
				textAreaConsole.append("linha " + e.getLinha() + ": rótulo não definido!\n");
			}
		 catch (ExecaoRotuloSemInstrucao e) {
				// TODO Auto-generated catch block
				textAreaConsole.append("linha " + e.getLinha() + ": rotulo sem intruçao!\n");
			}
		 catch (ExecaoMontador e) {
				// TODO Auto-generated catch block
				textAreaConsole.append("linha " + e.getLinha() + ": erro de montagem!\n");
			}
		
		carregaTabelaDeExecucao();
	}
	
	private void carregaTabelaDeExecucao(){

		if (rdbtnBinaryExecute.isSelected()){
			carregaTabelaDeExecucaoBin();			
		}
		else if (rdbtnHexadecimalExecute.isSelected())
			carregaTabelaDeExecucaoHex();
		else{
			carregaTabelaDeExecucaoDec();
		}			

		
	}
	
	private void carregaTabelaDeExecucaoDec(){
		
		for (int i = 0; i < listaDeExecucao.size(); i++) {
			
			tableExecute.setValueAt(listaDeExecucao.get(i).getRotulo(), i, 0);
			tableExecute.setValueAt(String.valueOf(listaDeExecucao.get(i).getEnderecoDecimal()), i, 1);
			tableExecute.setValueAt(ConversaoDeBases.binToDecUnsigned(listaDeExecucao.get(i).getCodigoMaquina()), i, 2);
			tableExecute.setValueAt(listaDeExecucao.get(i).getInstrucaoMips(), i, 3);
		}
		
	}

	private void carregaTabelaDeExecucaoBin(){
		
		for (int i = 0; i < listaDeExecucao.size(); i++) {
			tableExecute.setValueAt(listaDeExecucao.get(i).getRotulo(), i, 0);
			tableExecute.setValueAt(ConversaoDeBases.DecToBin(listaDeExecucao.get(i).getEnderecoDecimal()), i, 1);
			tableExecute.setValueAt(listaDeExecucao.get(i).getCodigoMaquina(), i, 2);
			tableExecute.setValueAt(listaDeExecucao.get(i).getInstrucaoMips(), i, 3);
		}
		
	}
	
	private void carregaTabelaDeExecucaoHex(){
		
		for (int i = 0; i < listaDeExecucao.size(); i++) {
			tableExecute.setValueAt(listaDeExecucao.get(i).getRotulo(), i, 0);
			tableExecute.setValueAt(ConversaoDeBases.decToHex(listaDeExecucao.get(i).getEnderecoDecimal()), i, 1);
			tableExecute.setValueAt(ConversaoDeBases.binToHex(listaDeExecucao.get(i).getCodigoMaquina()), i, 2);
			tableExecute.setValueAt(listaDeExecucao.get(i).getInstrucaoMips(), i, 3);
		}
		
	}
	
	private void executaProximaInstrucao(){
		try {	
			mips.executaProximaInstrucao();
			
			 tableExecute.repaint();
			
			 tableExecute.getColumnModel().getColumn(3).setCellRenderer(new RenderCell(mips.pc() < 0 ? 0 : mips.pc() / 4));
			 tableExecute.repaint();
			
			
		} catch (ExecaoInstrucaoInexistente e) {
			
			textAreaConsole.append("endereço " + e.getEndereco() + ": instrução inválida!\n");
			
		} catch (ExecaoHalt e) {
			
			textAreaConsole.append("endereço " + e.getEndereco() + ": halt!\n");
		} finally {
			recarregaMemoria();
			recarregaRegistradores();	
		}	
	}
	
	private void executaTodasInstrucoes(){
		try {
			mips.executaTodasInstrucoes();
		
			
		} catch (ExecaoInstrucaoInexistente e) {
			
			textAreaConsole.append("endereço " + e.getEndereco() + ": instrução inválida!\n");			
		} catch (ExecaoHalt e) {
			
			textAreaConsole.append("endereço " + e.getEndereco() + ": halt!\n");
		} finally {
			tableExecute.getColumnModel().getColumn(3).setCellRenderer(new RenderCell(mips.pc() < 0 ? 0 : mips.pc() / 4));
			tableExecute.repaint();
			recarregaMemoria();
			recarregaRegistradores();
			
		}
		
	}
	
	
	private void carregaRegistradores(){
		//carrega os registradores do simulador
		registradoresArray = mips.getRegistradores();
	}
	
	private void carregaMemoria(long start, long end){
		
		//carrega a memória do simulador
		memoriaArray = mips.getMemoria(start, end);	
	}
	
	private void recarregaRegistradores(){
		carregaRegistradores();
		
		if (rdbtnBinaryRegisters.isSelected()){
			carregaRegistradoresBin();			
		}
		else if (rdbtnHexadecimalRegisters.isSelected())
			carregaRegistradoresHex();
		else{
			carregaRegistradoresDec();
		}			
	}
	
	//Carrega registradores para visualização
	private void carregaRegistradoresBin(){
		for (int i = 0; i < 32; i++) {
			tableRegister.setValueAt(registradoresArray[i], i, 2);
		}
		
		//Atualiza o valor do pc
		tableRegister.setValueAt(ConversaoDeBases.DecToBin(mips.pc()), 32, 2);
	}
	
	//Carrega registradores para visualização
	private void carregaRegistradoresHex(){	
		for (int i = 0; i < 32; i++) {
			tableRegister.setValueAt(ConversaoDeBases.binToHex(registradoresArray[i]), i, 2);
		}	
		
		//Atualiza o valor do pc
		tableRegister.setValueAt(ConversaoDeBases.decToHex(mips.pc()), 32, 2);
	}
	
	private void carregaRegistradoresDec(){
		for (int i = 0; i < 32; i++) {
			tableRegister.setValueAt(ConversaoDeBases.binToDecSigned(registradoresArray[i]), i, 2);
		}		

		//Atualiza o valor do pc
		tableRegister.setValueAt(mips.pc(), 32, 2);
	}
	
	private void recarregaMemoria(){
		memoryStartValue = (long)(Long) spinnerStart.getValue();
		memoryEndValue = memoryStartValue + 399;
		
		carregaMemoria(memoryStartValue, memoryEndValue);
		
		if (rdbtnBinaryMemory.isSelected()){
			carregaMemoriaBin();			
		}
		else if (rdbtnHexadecimalMemory.isSelected())
			carregaMemoriaHex();
		else{
			carregaMemoriaDec();
		}			
	}
	
	//
	private void carregaMemoriaHex(){
		
		long start = ((long) (Long) spinnerStart.getValue());
		
		for (int i = 0; i < memoriaArray.length; i+=16) {
			
					
			//Exibe o endereço
			tableMemory.setValueAt(ConversaoDeBases.decToHex(start + i), i/16, 0);
			
			
			//Exibe os valores
			tableMemory.setValueAt(ConversaoDeBases.binToHex(memoriaArray[i] + memoriaArray[i+1] + memoriaArray[i+2] + memoriaArray[i+3]), i/16, 1);
			tableMemory.setValueAt(ConversaoDeBases.binToHex(memoriaArray[i+4] + memoriaArray[i+5] + memoriaArray[i+6] + memoriaArray[i+7]), i/16, 2);
			tableMemory.setValueAt(ConversaoDeBases.binToHex(memoriaArray[i+8] + memoriaArray[i+9] + memoriaArray[i+10] + memoriaArray[i+11]), i/16, 3);
			tableMemory.setValueAt(ConversaoDeBases.binToHex(memoriaArray[i+12] + memoriaArray[i+13] + memoriaArray[i+14] + memoriaArray[i+15]), i/16, 4);
		}
	}

	private void carregaMemoriaDec(){
		
		long start = ((long) (Long) spinnerStart.getValue());
		
		for (int i = 0; i < memoriaArray.length; i+=16) {
					
			//Exibe o endereço
			tableMemory.setValueAt((start + i), i/16, 0);
			
			
			//Exibe os valores
			tableMemory.setValueAt(ConversaoDeBases.binToDecSigned(memoriaArray[i] + memoriaArray[i+1] + memoriaArray[i+2] + memoriaArray[i+3]), i/16, 1);
			tableMemory.setValueAt(ConversaoDeBases.binToDecSigned(memoriaArray[i+4] + memoriaArray[i+5] + memoriaArray[i+6] + memoriaArray[i+7]), i/16, 2);
			tableMemory.setValueAt(ConversaoDeBases.binToDecSigned(memoriaArray[i+8] + memoriaArray[i+9] + memoriaArray[i+10] + memoriaArray[i+11]), i/16, 3);
			tableMemory.setValueAt(ConversaoDeBases.binToDecSigned(memoriaArray[i+12] + memoriaArray[i+13] + memoriaArray[i+14] + memoriaArray[i+15]), i/16, 4);
		}

	}
	
	
	private void carregaMemoriaBin(){
		
		long start = ((long) (Long) spinnerStart.getValue());
		
		for (int i = 0; i < memoriaArray.length; i+=16) {
					
			//Exibe o endereço
			tableMemory.setValueAt(ConversaoDeBases.DecToBin(start + i), i/16, 0);
			
			
			//Exibe os valores
			tableMemory.setValueAt(memoriaArray[i] + memoriaArray[i+1] + memoriaArray[i+2] + memoriaArray[i+3], i/16, 1);
			tableMemory.setValueAt(memoriaArray[i+4] + memoriaArray[i+5] + memoriaArray[i+6] + memoriaArray[i+7], i/16, 2);
			tableMemory.setValueAt(memoriaArray[i+8] + memoriaArray[i+9] + memoriaArray[i+10] + memoriaArray[i+11], i/16, 3);
			tableMemory.setValueAt(memoriaArray[i+12] + memoriaArray[i+13] + memoriaArray[i+14] + memoriaArray[i+15], i/16, 4);
		}

	}
		
	private void gravarMudancas(){
		int msgBox = JOptionPane.showConfirmDialog(frmMipsSimulator,
				"You want to write changes?", "Exit",
				JOptionPane.YES_NO_CANCEL_OPTION);

		// Yes or No
		if (msgBox < 2) {

			if (msgBox == JOptionPane.YES_OPTION) {

				// save file
				salvar();
			}
		}
	}	
	
	private void exit() {

		if (editorPaneCode.isEnabled())
			gravarMudancas();
		
		frmMipsSimulator.setVisible(false);
		System.exit(1);
	}

	/**
	 * Create the application.
	 */
	public Janela() {
		//instância o simulador MIPS
		mips = new Simulador();
		
		tamanhoMemoria = mips.tamanhoMemoria();
		
		carregaMemoria(memoryStartValue, memoryEndValue);
		carregaRegistradores();
		
		//inicializa a janela
		initialize();
						
		//Carrega memória para a tabela com valores representados em Hexadecimal
		carregaMemoriaHex();
		
		//Carrega registradores para a tabela com valores representados em Hexadecimal
		carregaRegistradoresHex();
	}
	

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmMipsSimulator = new JFrame();
		frmMipsSimulator.setTitle("MIPS Simulator");
		frmMipsSimulator.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent arg0) {
				exit();
			}
		});
		frmMipsSimulator.setResizable(false);
		frmMipsSimulator.setBounds(100, 100, 1064, 774);
		frmMipsSimulator.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		jFChosen = new JFileChooser();
		jFChosen.setFileFilter(new FileFilter() {
			
			@Override
			public String getDescription() {
				// TODO Auto-generated method stub
				return "Arquivo assembly MIPS (*.asm)";
			}
			
			@Override
			public boolean accept(File arg0) {
				// TODO Auto-generated method stub
				return arg0.getName().toLowerCase().endsWith(".asm") || arg0.isDirectory();
			}
		});
			
		
		
		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		
		JPanel panel_2 = new JPanel();
		panel_2.setBorder(new TitledBorder(null, "Memory", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panel_3 = new JPanel();
		panel_3.setBorder(new TitledBorder(null, "Console", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panel_4 = new JPanel();
		panel_4.setBorder(new TitledBorder(null, "Registers", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GroupLayout groupLayout = new GroupLayout(frmMipsSimulator.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
							.addComponent(panel_3, GroupLayout.PREFERRED_SIZE, 792, GroupLayout.PREFERRED_SIZE)
							.addComponent(panel_2, GroupLayout.PREFERRED_SIZE, 792, GroupLayout.PREFERRED_SIZE))
						.addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 791, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel_4, GroupLayout.PREFERRED_SIZE, 246, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.TRAILING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addComponent(panel_4, GroupLayout.PREFERRED_SIZE, 698, Short.MAX_VALUE)
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(tabbedPane, GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(panel_2, GroupLayout.PREFERRED_SIZE, 211, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(panel_3, GroupLayout.PREFERRED_SIZE, 148, GroupLayout.PREFERRED_SIZE)))
					.addGap(22))
		);
		
		JScrollPane scrollPane_4 = new JScrollPane();
		
		rdbtnHexadecimalRegisters = new JRadioButton("Hexadecimal values");
		rdbtnHexadecimalRegisters.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalRegisters.setSelected(true);
				rdbtnDecimalRegisters.setSelected(false);
				rdbtnBinaryRegisters.setSelected(false);
				
				recarregaRegistradores();
			}
		});
		
		rdbtnHexadecimalRegisters.setSelected(true);
		
		
		rdbtnDecimalRegisters = new JRadioButton("Decimal values");
		rdbtnDecimalRegisters.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalRegisters.setSelected(false);
				rdbtnDecimalRegisters.setSelected(true);
				rdbtnBinaryRegisters.setSelected(false);
				
				recarregaRegistradores();
			}
		});
	
		
		rdbtnBinaryRegisters = new JRadioButton("Binary Values");
		rdbtnBinaryRegisters.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalRegisters.setSelected(false);
				rdbtnDecimalRegisters.setSelected(false);
				rdbtnBinaryRegisters.setSelected(true);
				
				recarregaRegistradores();
			}
		});
		
		GroupLayout gl_panel_4 = new GroupLayout(panel_4);
		gl_panel_4.setHorizontalGroup(
			gl_panel_4.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane_4, GroupLayout.DEFAULT_SIZE, 236, Short.MAX_VALUE)
				.addGroup(gl_panel_4.createSequentialGroup()
					.addGap(34)
					.addGroup(gl_panel_4.createParallelGroup(Alignment.LEADING)
						.addComponent(rdbtnBinaryRegisters, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE)
						.addComponent(rdbtnDecimalRegisters, GroupLayout.PREFERRED_SIZE, 135, GroupLayout.PREFERRED_SIZE)
						.addComponent(rdbtnHexadecimalRegisters, GroupLayout.PREFERRED_SIZE, 164, GroupLayout.PREFERRED_SIZE))
					.addContainerGap(38, Short.MAX_VALUE))
		);
		gl_panel_4.setVerticalGroup(
			gl_panel_4.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_4.createSequentialGroup()
					.addComponent(scrollPane_4, GroupLayout.PREFERRED_SIZE, 557, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addComponent(rdbtnHexadecimalRegisters)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(rdbtnDecimalRegisters)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(rdbtnBinaryRegisters)
					.addContainerGap(24, Short.MAX_VALUE))
		);
		
		tableRegister = new JTable();
		tableRegister.setModel(new DefaultTableModel(
			new Object[][] {
				{"$zero", new Integer(0), null},
				{"$at", new Integer(1), null},
				{"$v0", new Integer(2), null},
				{"$v1", new Integer(3), null},
				{"$a0", new Integer(4), null},
				{"$a1", new Integer(5), null},
				{"$a2", new Integer(6), null},
				{"$a3", new Integer(7), null},
				{"$t0", new Integer(8), null},
				{"$t1", new Integer(9), null},
				{"$t2", new Integer(10), null},
				{"$t3", new Integer(11), null},
				{"$t4", new Integer(12), null},
				{"$t5", new Integer(13), null},
				{"$t6", new Integer(14), null},
				{"$t7", new Integer(15), null},
				{"$s0", new Integer(16), null},
				{"$s1", new Integer(17), null},
				{"$s2", new Integer(18), null},
				{"$s3", new Integer(19), null},
				{"$s4", new Integer(20), null},
				{"$s5", new Integer(21), null},
				{"$s6", new Integer(22), null},
				{"$s7", new Integer(23), null},
				{"$t8", new Integer(24), null},
				{"$t9", new Integer(25), null},
				{"$k0", new Integer(26), null},
				{"$k1", new Integer(27), null},
				{"$gp", new Integer(28), null},
				{"$sp", new Integer(29), null},
				{"$fp", new Integer(30), null},
				{"$ra", new Integer(31), null},
				{"pc", null, null},
			},
			new String[] {
				"Name", "Number", "Value"
			}
		) {
			Class[] columnTypes = new Class[] {
				String.class, Short.class, String.class
			};
			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}
			boolean[] columnEditables = new boolean[] {
				false, false, false
			};
			public boolean isCellEditable(int row, int column) {
				return columnEditables[column];
			}
		});
		tableRegister.getColumnModel().getColumn(0).setPreferredWidth(55);
		tableRegister.getColumnModel().getColumn(1).setPreferredWidth(57);
		tableRegister.getColumnModel().getColumn(2).setPreferredWidth(99);
		tableRegister.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		scrollPane_4.setViewportView(tableRegister);
		panel_4.setLayout(gl_panel_4);
		
		JScrollPane scrollPane_3 = new JScrollPane();
		GroupLayout gl_panel_3 = new GroupLayout(panel_3);
		gl_panel_3.setHorizontalGroup(
			gl_panel_3.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_3.createSequentialGroup()
					.addContainerGap()
					.addComponent(scrollPane_3, GroupLayout.PREFERRED_SIZE, 770, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		gl_panel_3.setVerticalGroup(
			gl_panel_3.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_3.createSequentialGroup()
					.addComponent(scrollPane_3, GroupLayout.PREFERRED_SIZE, 120, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		
		textAreaConsole = new JTextArea();
		textAreaConsole.setEditable(false);
		scrollPane_3.setViewportView(textAreaConsole);
		panel_3.setLayout(gl_panel_3);
		
		JLabel lblStart = new JLabel("Start");
		
		rdbtnHexadecimalMemory = new JRadioButton("Hexadecimal values");
		rdbtnHexadecimalMemory.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				rdbtnHexadecimalMemory.setSelected(true);
				rdbtnDecimalMemory.setSelected(false);
				rdbtnBinaryMemory.setSelected(false);
				
				recarregaMemoria();
				
			}
		});
		rdbtnHexadecimalMemory.setSelected(true);
				
		rdbtnDecimalMemory = new JRadioButton("Decimal values");
		rdbtnDecimalMemory.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalMemory.setSelected(false);
				rdbtnDecimalMemory.setSelected(true);
				rdbtnBinaryMemory.setSelected(false);
				
				recarregaMemoria();
			}
		});
		rdbtnBinaryMemory = new JRadioButton("Binary Values");
		rdbtnBinaryMemory.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalMemory.setSelected(false);
				rdbtnDecimalMemory.setSelected(false);
				rdbtnBinaryMemory.setSelected(true);
				
				recarregaMemoria();
			}
		});
		
		spinnerStart = new JSpinner();
		spinnerStart.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				
				spinnerStart.setValue(Long.valueOf(((long) (Long) spinnerStart.getValue()) - (((long) (Long) spinnerStart.getValue()) % 16)));
				recarregaMemoria();
			}
		});
		spinnerStart.setModel(new SpinnerNumberModel(new Long(0), new Long(0), new Long(mips.tamanhoMemoria()-400), new Long(16)));
		
		JScrollPane scrollPane_1 = new JScrollPane();
		GroupLayout gl_panel_2 = new GroupLayout(panel_2);
		gl_panel_2.setHorizontalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_2.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel_2.createParallelGroup(Alignment.LEADING)
						.addComponent(scrollPane_1, GroupLayout.PREFERRED_SIZE, 764, GroupLayout.PREFERRED_SIZE)
						.addGroup(gl_panel_2.createSequentialGroup()
							.addComponent(lblStart)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(spinnerStart, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE)
							.addGap(169)
							.addComponent(rdbtnHexadecimalMemory)
							.addGap(18)
							.addComponent(rdbtnDecimalMemory, GroupLayout.PREFERRED_SIZE, 135, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(rdbtnBinaryMemory)))
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		gl_panel_2.setVerticalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_2.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel_2.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_panel_2.createParallelGroup(Alignment.BASELINE)
							.addComponent(lblStart)
							.addComponent(spinnerStart, GroupLayout.PREFERRED_SIZE, 26, GroupLayout.PREFERRED_SIZE))
						.addGroup(gl_panel_2.createParallelGroup(Alignment.BASELINE)
							.addComponent(rdbtnHexadecimalMemory)
							.addComponent(rdbtnDecimalMemory)
							.addComponent(rdbtnBinaryMemory)))
					.addGap(18)
					.addComponent(scrollPane_1, GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)
					.addGap(7))
		);
		
		tableMemory = new JTable();
		tableMemory.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tableMemory.setRowSelectionAllowed(false);
		tableMemory.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
				{null, null, null, null, null},
			},
			new String[] {
				"Address", "Value (+0)", "Value (+4)", "Value (+8)", "Value (+12)"
			}
		) {
			Class[] columnTypes = new Class[] {
				String.class, String.class, String.class, String.class, String.class
			};
			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}
			boolean[] columnEditables = new boolean[] {
				false, false, false, false, false
			};
			public boolean isCellEditable(int row, int column) {
				return columnEditables[column];
			}
		});
		tableMemory.getColumnModel().getColumn(0).setPreferredWidth(93);
		tableMemory.getColumnModel().getColumn(1).setPreferredWidth(121);
		tableMemory.getColumnModel().getColumn(2).setPreferredWidth(126);
		tableMemory.getColumnModel().getColumn(3).setPreferredWidth(131);
		tableMemory.getColumnModel().getColumn(4).setPreferredWidth(118);
		scrollPane_1.setViewportView(tableMemory);
		panel_2.setLayout(gl_panel_2);
		
		JPanel panelFile = new JPanel();
		tabbedPane.addTab("File", null, panelFile, null);
		
		JScrollPane scrollPane = new JScrollPane();		
		GroupLayout gl_panelFile = new GroupLayout(panelFile);
		gl_panelFile.setHorizontalGroup(
			gl_panelFile.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panelFile.createSequentialGroup()
					.addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 785, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		gl_panelFile.setVerticalGroup(
			gl_panelFile.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)
		);
		
		editorPaneCode = new JEditorPane();
		editorPaneCode.setBackground(Color.LIGHT_GRAY);
		editorPaneCode.setEnabled(false);
		scrollPane.setViewportView(editorPaneCode);
		panelFile.setLayout(gl_panelFile);
		
		tln = new TextLineNumber(editorPaneCode);
		scrollPane.setRowHeaderView(tln);

		
		JPanel panelExecute = new JPanel();
		tabbedPane.addTab("Execute", null, panelExecute, null);
		
		JScrollPane scrollPane_2 = new JScrollPane();
		
		rdbtnHexadecimalExecute = new JRadioButton("Hexadecimal values");
		rdbtnHexadecimalExecute.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				rdbtnHexadecimalExecute.setSelected(true);
				rdbtnDecimalExecute.setSelected(false);
				rdbtnBinaryExecute.setSelected(false);
				
				carregaTabelaDeExecucao();
				
			}
		});
		rdbtnHexadecimalExecute.setSelected(true);
				
		rdbtnDecimalExecute = new JRadioButton("Decimal values");
		rdbtnDecimalExecute.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalExecute.setSelected(false);
				rdbtnDecimalExecute.setSelected(true);
				rdbtnBinaryExecute.setSelected(false);
				
				carregaTabelaDeExecucao();
			}
		});
		rdbtnBinaryExecute = new JRadioButton("Binary Values");
		rdbtnBinaryExecute.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				rdbtnHexadecimalExecute.setSelected(false);
				rdbtnDecimalExecute.setSelected(false);
				rdbtnBinaryExecute.setSelected(true);
				
				carregaTabelaDeExecucao();
			}
		});
		
		GroupLayout gl_panelExecute = new GroupLayout(panelExecute);
		gl_panelExecute.setHorizontalGroup(
			gl_panelExecute.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_panelExecute.createSequentialGroup()
					.addContainerGap()
					.addComponent(scrollPane_2, GroupLayout.PREFERRED_SIZE, 773, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
				.addGroup(gl_panelExecute.createSequentialGroup()
					.addContainerGap(328, Short.MAX_VALUE)
					.addComponent(rdbtnHexadecimalExecute, GroupLayout.PREFERRED_SIZE, 164, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addComponent(rdbtnDecimalExecute, GroupLayout.PREFERRED_SIZE, 135, GroupLayout.PREFERRED_SIZE)
					.addComponent(rdbtnBinaryExecute, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE)
					.addGap(19))
		);
		gl_panelExecute.setVerticalGroup(
			gl_panelExecute.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panelExecute.createSequentialGroup()
					.addComponent(scrollPane_2, GroupLayout.PREFERRED_SIZE, 248, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED, 17, Short.MAX_VALUE)
					.addGroup(gl_panelExecute.createParallelGroup(Alignment.LEADING)
						.addComponent(rdbtnHexadecimalExecute)
						.addComponent(rdbtnDecimalExecute)
						.addComponent(rdbtnBinaryExecute)))
		);
		

		tableModelExecute = new DefaultTableModel(
				new Object[][] {
				},
				new String[] {
					"Label", "Address", "Code", "Basic"
				}
			);

		tableExecute = new JTable(tableModelExecute);

		tableExecute.getColumnModel().getColumn(0).setPreferredWidth(93);
		tableExecute.getColumnModel().getColumn(1).setPreferredWidth(161);
		tableExecute.getColumnModel().getColumn(2).setPreferredWidth(148);
		tableExecute.getColumnModel().getColumn(3).setPreferredWidth(241);
		tableExecute.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tableExecute.setRowSelectionAllowed(false);
		tableExecute.setCellSelectionEnabled(true);
		scrollPane_2.setViewportView(tableExecute);
		panelExecute.setLayout(gl_panelExecute);
		frmMipsSimulator.getContentPane().setLayout(groupLayout);
		
		JMenuBar menuBar = new JMenuBar();
		frmMipsSimulator.setJMenuBar(menuBar);
		
		btnNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				
				//Ativa os demais botões
				novoPrograma();
				
			}
		});
		btnNew.setMnemonic('N');
		menuBar.add(btnNew);
		
		btnOpen = new JButton("Open");
		btnOpen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				abrir();
				
			}
		});
		btnOpen.setMnemonic('O');
		menuBar.add(btnOpen);
		
		btnSave = new JButton("Save");
		btnSave.setEnabled(false);
		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				salvar();
				
			}
		});
		btnSave.setMnemonic('S');
		menuBar.add(btnSave);
		
		btnSaveAs = new JButton("Save as");
		btnSaveAs.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				salvarComo();
			}
		});
		btnSaveAs.setEnabled(false);
		btnSaveAs.setMnemonic('v');
		menuBar.add(btnSaveAs);
		
		btnAssemble = new JButton("Assemble");
		btnAssemble.setEnabled(false);
		btnAssemble.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				assemble();
			}
		});
		btnAssemble.setMnemonic('A');
		menuBar.add(btnAssemble);
		
		btnExecute = new JButton("Execute");
		btnExecute.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				executaTodasInstrucoes();				
			}
		});
		btnExecute.setEnabled(false);
		btnExecute.setMnemonic('E');
		menuBar.add(btnExecute);
		
		btnStep = new JButton("Step");
		btnStep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				executaProximaInstrucao();
			}
		});
		btnStep.setEnabled(false);
		btnStep.setMnemonic('t');
		menuBar.add(btnStep);
	}
}